#pragma once

#include <ode/common.h>
#include "drawable.h"
#include <osg/Matrix>
#include "corebase_global.h"

struct dContact;

namespace osg
{
	class MatrixTransform;
}

namespace CoreBase
{
	class ODEGeomWrap;
	class PointAxis;
	class Transform;
	class TransformableImpl;

	class COREBASE_EXPORT Transformable : public Drawable
	{
	public:
		enum CoordSysEnum
		{
			REL_CS, ///< The Transform coordinate system is relative to the parent
			ABS_CS  ///< The Transform coordinate system is absolute
		};
		static const std::string COLLISION_GEODE_ID;
		Transformable(ActorBase* owneractor,const QString& name = "Transformable");
		typedef osg::MatrixTransform TransformableNode;
		Transformable(TransformableNode& node,ActorBase* owneractor, const QString& name = "Transformable");
	protected:
		virtual ~Transformable();
		bool								_haveInScene;
	public:
		virtual bool addChild(Drawable* child);
		virtual void removeChild(Drawable* child);
		virtual void setTransform(const Transform& xform, CoordSysEnum cs = ABS_CS);
		virtual void getTransform(Transform& xform, CoordSysEnum cs = ABS_CS) const;
		TransformableNode* getMatrixNode();
		const TransformableNode* getMatrixNode() const;
		const osg::Matrix& getMatrix() const;
		void setMatrix(const osg::Matrix& mat);
		void setTraverseMask(int mask);
		int getTrasverseMask();
		virtual bool filterContact(dContact* /*contact*/, Transformable* /*collider*/) 
		{ return false; }
		static bool getAbsoluteMatrix(const osg::Node* node, osg::Matrix& wcmatrix);
		void setNormalRescaling(bool enable);
		bool setNormalRescaling() const;
		dGeomID getGeomID() const;
		QString getCollisionGeomType() const;
		void getCollisionGeomDimensions(std::vector<float>& dimensions);
		void setCollisionDetection(bool enabled);
		bool getCollisionDetection() const;
		void setCollisionGeom(dGeomID geom);
		void setCollisionSphere(float radius);
		void setCollisionSphere(osg::Node* node = 0);
		void setCollisionBox(float lx, float ly, float lz);
		void setCollisionBox(osg::Node* node = 0);
		//void SetCollisionCylinder(float radius, float length);
		//void SetCollisionCylinder(osg::Node* node = NULL);
		//void SetCollisionCappedCylinder(float radius, float length);
		//void SetCollisionCappedCylinder(osg::Node* node = NULL);
		//void SetCollisionRay(float length);
		void setCollisionMesh(osg::Node* node = NULL);
		void clearCollisionGeometry();
		virtual void prePhysicsStepUpdate();
		virtual void postPhysicsStepUpdate() {}
		void renderCollisionGeometry(bool enable = true, bool wireFrame = false);
		bool getRenderCollisionGeometry() const;
		void setCollisionCategoryBits(unsigned long bits);
		unsigned long getCollisionCategoryBits() const;
		void setCollisionCollideBits(unsigned long bits);
		unsigned long getCollisionCollideBits() const;
		const ODEGeomWrap* getGeomWrapper() const;
		ODEGeomWrap* getGeomWrapper();
		bool getNormalRescaling() const;
		virtual osg::Node* getOSGNode();
		virtual const osg::Node* getOSGNode() const;
		virtual void addedToScene(Scene* scene);
	private:
		void ctor();
		TransformableImpl*					_impl;
		int									_nodeMask;
		void removeRenderedCollisionGeometry();
	};
}
